﻿Imports System.Net
Imports System.Text
Imports System.Web
Imports System.IO
Imports System.Runtime.Serialization
Imports Sgml
Imports System.Xml

Partial Class TwitterClient

    ''' <summary>
    ''' ステータスをポストした結果として返されるJSONを格納します。
    ''' </summary>
    ''' <remarks></remarks>
    ''' 
    <DataContract()> _
    Private Class UpdateStatusJsonResult
        Private _statusLi As String
        <DataMember(Name:="status_li")> _
        Public Property StatusListItem() As String
            Get
                Return _statusLi
            End Get
            Set(ByVal value As String)
                _statusLi = value
            End Set
        End Property

        Private _statusCount As Integer
        <DataMember(Name:="status_count")> _
        Public Property StatusCount() As Integer
            Get
                Return _statusCount
            End Get
            Set(ByVal value As Integer)
                _statusCount = value
            End Set
        End Property
    End Class

    ''' <summary>
    ''' ステータス文字列を指定して投稿します。
    ''' </summary>
    ''' <param name="status">ステータス文字列</param>
    ''' <returns>投稿されたステータス</returns>
    ''' <remarks></remarks>
    Public Function UpdateStatus(ByVal status As String) As TwitterStatus
        Return UpdateStatus(status, -1)
    End Function

    ''' <summary>
    ''' ステータス文字列と返信先のステータスを指定して投稿します。
    ''' </summary>
    ''' <param name="status">ステータス文字列</param>
    ''' <param name="inReplyToStatus">返信先のステータス</param>
    ''' <returns>投稿されたステータス</returns>
    ''' <remarks></remarks>
    Public Function UpdateStatus(ByVal status As String, ByVal inReplyToStatus As TwitterStatus) As TwitterStatus
        Return UpdateStatus(status, inReplyToStatus.StatusID)
    End Function

    ''' <summary>
    ''' ステータス文字列と返信先のステータスIDを指定して投稿します。
    ''' </summary>
    ''' <param name="status">ステータス文字列</param>
    ''' <param name="inReplyToStatusID">返信先のステータスID</param>
    ''' <returns>投稿されたステータス</returns>
    ''' <remarks></remarks>
    Public Function UpdateStatus(ByVal status As String, ByVal inReplyToStatusID As Long) As TwitterStatus
        If Not IsLogined Then
            Throw New InvalidOperationException(StrThisInstanceIsNotLoginedYet)
        End If

        Dim funcRet As TwitterStatus
        Dim url As String = String.Format("{0}{1}", My.Resources.TwitterUrl, My.Resources.TwitterUpdateStatusPath)
        Dim req As HttpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)
        req.SetTwitterXHRPostHeaders(My.Resources.TwitterUrl, _cookies)
        Dim sbPost As New StringBuilder()
        sbPost.AppendFormat("{0}={1}&", HttpUtility.UrlEncode(_authenticityTokenFiledName), HttpUtility.UrlEncode(_authenticityToken))
        sbPost.AppendFormat("{0}={1}&", "status", HttpUtility.UrlEncode(status, Encoding.UTF8))
        sbPost.AppendFormat("{0}={1}&", "twttr", "true")
        sbPost.AppendFormat("{0}={1}", "return_rendered_status", "true")
        If (inReplyToStatusID >= 0) Then
            sbPost.AppendFormat("&{0}={1}", "in_reply_to_status_id", inReplyToStatusID)
        End If
        Dim strPost As String = sbPost.ToString()
        req.PostString(strPost)
        Using res As HttpWebResponse = DirectCast(req.GetResponse(), HttpWebResponse)
            Select Case res.StatusCode
                Case HttpStatusCode.OK
                    res.LoadCookies(_cookies)
                    Dim xmlRes As XmlDocument = Nothing
                    Using srRes As New StreamReader(res.GetResponseStream())
                        Dim jsonResult As UpdateStatusJsonResult = res.GetResponseAsJson(Of UpdateStatusJsonResult)()
                        If Not String.IsNullOrEmpty(jsonResult.StatusListItem) Then
                            xmlRes.LoadSgml(jsonResult.StatusListItem)
                        End If
                    End Using
                    If xmlRes IsNot Nothing Then
                        funcRet = ParseStatusListItem(xmlRes.DocumentElement, TimelineType.Home, Nothing)
                    Else
                        funcRet = Nothing
                    End If
                Case Else
                    funcRet = Nothing
            End Select
        End Using
        Return funcRet
    End Function

    ''' <summary>
    ''' 投稿したステータスを削除します。
    ''' </summary>
    ''' <param name="statusID">ステータスID</param>
    ''' <returns>削除に成功すればTrue、失敗すればFalse</returns>
    ''' <remarks></remarks>
    Public Function DestroyStatus(ByVal statusID As Long) As Boolean
        If Not IsLogined Then
            Throw New InvalidOperationException(StrThisInstanceIsNotLoginedYet)
        End If

        Dim funcRet As Boolean
        Dim url As String = String.Format("{0}{1}{2}", My.Resources.TwitterUrl, My.Resources.TwitterDestroyStatusPath, statusID)
        Dim req As HttpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)
        req.SetTwitterXHRPostHeaders(My.Resources.TwitterUrl, _cookies)
        Dim sbPost As New StringBuilder()
        sbPost.AppendFormat("{0}={1}&", HttpUtility.UrlEncode(_authenticityTokenFiledName), HttpUtility.UrlEncode(_authenticityToken))
        sbPost.AppendFormat("{0}={1}", "latest_status", "false") 'TODO:最新かどうかの判別はできないか
        Dim strPost As String = sbPost.ToString()
        req.PostString(strPost)
        Using res As HttpWebResponse = DirectCast(req.GetResponse(), HttpWebResponse)
            Select Case res.StatusCode
                Case HttpStatusCode.OK
                    funcRet = True
                Case Else
                    funcRet = False
            End Select
        End Using
        Return funcRet
    End Function

    ''' <summary>
    ''' 指定したステータスをお気に入りに追加します。
    ''' </summary>
    ''' <param name="statusID">ステータスID</param>
    ''' <returns>追加に成功すればTrue、失敗すればFalse</returns>
    ''' <remarks></remarks>
    Public Function CreateFavorite(ByVal statusID As Long) As Boolean
        If Not IsLogined Then
            Throw New InvalidOperationException(StrThisInstanceIsNotLoginedYet)
        End If

        Dim funcRet As Boolean
        Dim url As String = String.Format("{0}{1}{2}", My.Resources.TwitterUrl, My.Resources.TwitterCreateFavoritePath, statusID)
        Dim req As HttpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)
        req.SetTwitterXHRPostHeaders(My.Resources.TwitterUrl, _cookies)
        Dim sbPost As New StringBuilder()
        sbPost.AppendFormat("{0}={1}", HttpUtility.UrlEncode(_authenticityTokenFiledName), HttpUtility.UrlEncode(_authenticityToken))
        Dim strPost As String = sbPost.ToString()
        req.PostString(strPost)
        Using res As HttpWebResponse = DirectCast(req.GetResponse(), HttpWebResponse)
            Select Case res.StatusCode
                Case HttpStatusCode.OK
                    funcRet = True
                Case Else
                    funcRet = False
            End Select
        End Using
        Return funcRet
    End Function

    ''' <summary>
    ''' 指定したステータスをお気に入りから削除します。
    ''' </summary>
    ''' <param name="statusID">ステータスID</param>
    ''' <returns>削除に成功すればTrue、失敗すればFalse</returns>
    ''' <remarks></remarks>
    Public Function DestroyFavorite(ByVal statusID As Long) As Boolean
        If Not IsLogined Then
            Throw New InvalidOperationException(StrThisInstanceIsNotLoginedYet)
        End If

        Dim funcRet As Boolean
        Dim url As String = String.Format("{0}{1}{2}", My.Resources.TwitterUrl, My.Resources.TwitterDestroyFavoritePath, statusID)
        Dim req As HttpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)
        req.SetTwitterXHRPostHeaders(My.Resources.TwitterUrl, _cookies)
        Dim sbPost As New StringBuilder()
        sbPost.AppendFormat("{0}={1}", HttpUtility.UrlEncode(_authenticityTokenFiledName), HttpUtility.UrlEncode(_authenticityToken))
        Dim strPost As String = sbPost.ToString()
        req.PostString(strPost)
        Using res As HttpWebResponse = DirectCast(req.GetResponse(), HttpWebResponse)
            Select Case res.StatusCode
                Case HttpStatusCode.OK
                    funcRet = True
                Case Else
                    funcRet = False
            End Select
        End Using
        Return funcRet
    End Function
End Class
